﻿#include "DAWorkFlow.h"
#include <QPointer>

class DAWorkFlowPrivate
{
    DA_IMPL_PUBLIC(DAWorkFlow)
public:
    DAWorkFlowPrivate(DAWorkFlow *p);
    QHash<DANodeMetaData, QPointer<DAAbstractNodeFactory>> _metaToFactory; ///< 记录prototype对应的工厂
    QList<DAAbstractNode::SharedPointer> _nodes;
    DAAbstractNode::SharedPointer _startNode; ///< 开始运行的节点
};

DAWorkFlowPrivate::DAWorkFlowPrivate(DAWorkFlow *p) : q_ptr(p), _startNode(nullptr) {}

DAWorkFlow::DAWorkFlow(QObject *p) : QObject(p), d_ptr(new DAWorkFlowPrivate(this)) {}

DAWorkFlow::~DAWorkFlow() {}

/**
 * @brief 注册工厂，工作流不保留工程的内存管理权
 * @param factory
 */
void DAWorkFlow::registFactory(DAAbstractNodeFactory *factory)
{
    QList<DANodeMetaData> mds = factory->getNodesMetaData();

    for (const DANodeMetaData &m : mds) {
        d_ptr->_metaToFactory[m] = factory;
    }
}

/**
 * @brief 注册工厂群，工作流不保留工程的内存管理权
 * @param factory
 */
void DAWorkFlow::registFactorys(const QList<DAAbstractNodeFactory *> factorys)
{
    for (DAAbstractNodeFactory *f : factorys) {
        registFactory(f);
    }
}

/**
 * @brief 工作流创建节点，FCWorkFlow保留节点的内存管理权
 * @param md
 * @return
 */
DAAbstractNode::SharedPointer DAWorkFlow::createNode(const DANodeMetaData &md)
{
    QPointer<DAAbstractNodeFactory> pointer = d_ptr->_metaToFactory.value(md, nullptr);

    if (pointer.isNull()) {
        return (nullptr);
    }

    DAAbstractNode::SharedPointer node = pointer->create(md);
    d_ptr->_nodes.append(node);
    emit nodeCreated(node);

    return (node);
}

/**
 * @brief 删除工作流节点，节点删除会触发@sa nodeStartRemove 信号
 *
 * @note node会调用detachAll函数移除所有依赖
 * @param n
 */
void DAWorkFlow::removeNode(DAAbstractNode::SharedPointer n)
{
    emit nodeStartRemove(n);
    n->detachAll();
    d_ptr->_nodes.removeAll(n);
}

/**
 * @brief 设置开始运行的节点,工作流开始必须指定一个开始节点
 * @param n
 */
void DAWorkFlow::setStartNode(DAAbstractNode::SharedPointer n)
{
    d_ptr->_startNode = n;
}
